#include "file_transfer.h"
#include "debug.h"
#include "tcpsocket.h"

// 接受文件传输协议头
int recv_protocol_head(int sockfd, file_protocol_t * p_head) {
    ssize_t rbytes;
    ssize_t total_received = 0;
    char * buffer = (char *)p_head;// 结构体转换为字符指针， 可以逐字节的读取或写入结构体的数据成员
    for (;;) {
        rbytes = tcp_recv_pack(sockfd, buffer + total_received, sizeof(file_protocol_t) - total_received);
        if (rbytes == -1) {
            DEBUG_INFO("[error] : %s ", strerror(errno));
            return -1;
        } else if(rbytes == 0 ) {
            DEBUG_INFO("[info] : the client has been shut down\n ");
        } else if(rbytes > 0) {
            total_received += rbytes;
            // 说明接受完毕
            if (total_received == sizeof(file_protocol_t)) {
                break;
            }
        }
    
    }
    if (total_received != sizeof(file_protocol_t)) {
        DEBUG_INFO("[error] : fail to receive data. \n");
        return -1;
    }
    return 0;
}
// 接受文件数据 , 将数据写到文件中
int recv_filedata(int sockfd, char * filename, size_t targetsize) {
    int sockfd;
    ssize_t rbytes = 0, wbytes = 0, file_size = 0;
    char buffer[1024] = {0};
    DEBUG_INFO("[info] :  filename %s  \n", filename);
    int fd = open(filename, O_WRONLY_CREATEIO_TRUNC, 0666);
    if (fd == -1) {
        DEBUG_INFO("[error] falied to open filename .\n");
        return -1;
    }
    for(;;) {
        rbytes = tcp_recv_pack(sockfd, buffer , sizeof(buffer));
        if (rbytes == -1) {
            DEBUG_INFO("[error]: %s ", strerror(errno));
            return -1;
        } else if (rbytes == 0) {
            DEBUG_INFO("[INFO]: The client hash been shut down \n");
            break;
        } else if (rbytes > 0) {
            //接收到的数据 写入文件中
            wbytes = write(fd, buffer, rbytes);
            if (wbytes != rbytes ) {
                DEBUG_INFO("[error] : fail to write data to file. \n");
                return -1;
            }
            file_size += rbytes;
            if (file_size == targetsize) {
                break;
            }
            
        }
    }
    close(cfd);
    return file_size;

}

// 接受文件头，获取文件大小和文件名； 接受数据，并将数据写入文件中
int  client_upload_file(int cfd) {
    char * filename;
    size_t filesize = 0, recvsize = 0;
    file_protocol_t head;
    int ret;
    // 获取到协议头中的信息
    ret = recv_protocol_head(cfd, &head);
    filename = head->filename;
    filesize = head->filesize;

    //获取数据
    recvsize = recv_filedata(cfd, filename, filesize);
    // 显示文件接受进度
    printf("recv %%%d \n", (int) (recvsize * 1.0 / filesize) * 100);
}

int send_protocol_head(const char * filename, int sockfd){
    file_protocol_t head;
    int filesize;
    int fd = open(filename, O_RDONLY);
    if (fd == -1) {
        DEBUG_INFO("[error] : fail to open file. \n");
        return -1;
    }
    // 将文件描述符的偏移量移动到文件末尾
    filesize = lseek(fd, 0, SEEK_END);
    close(fd);
    head.filesize = filesize;
    strcpy(head.filename, filename);
    // 客户端发送协议头数据
    int ret = tcp_send_pack(sockfd, &head, sizeof(head));
    if (ret != sizeof(file_protocol_t)) {
        DEBUG_INFO("[error] : fail to send protocol head. \n");
        return -1;
    }
    return filesize;
}
int upload_file(const char * filename, int sockfd) {
    int file_size, upload_size;
    int fd;
    ssize_t rbytes = 0, sbytes = 0;
    char buffer[1024] = {0};
    // 先发送协议头
    file_size = send_protocol_head(filename, sockfd);
    if (file_size < 0) {
        return -1;
    }
    fd = open(filename, O_RDONLY);
    if (fd == -1) {
        DEBUG_INFO("[error] : fail to open file. \n");
        return -1;
    }
    for(;;) {
        rbytes = read(fd, buffer, sizeof(buffer));
        if (rbytes == -1) {
            DEBUG_INFO(" fail to read data \n");
            return -1;
        }
        sbytes = tcp_send_pack(sockfd, buffer, rbytes);
        if (sbytes != rbytes) {
            DEBUG_INFO("[error] : fail to send data. \n");
            return -1;
        }
        upload_size += sbytes;
    }
    clsoe(fd);
    return upload_size;
}